package service_sys

import (
	"context"
	"go_web/internal/model/model_sys"
	"go_web/internal/repo/repo_sys"
	"go_web/internal/req/req_sys"
	"go_web/pkg/req"
	"go_web/pkg/res"
	"go_web/pkg/utils"
	"math"

	"github.com/fatih/structs"
	"github.com/jinzhu/copier"
	"gorm.io/gen"
	"gorm.io/gen/field"
)

type SysBindTypeService struct{}

// 创建新的 SysBindTypeService
func NewSysBindTypeService() *SysBindTypeService {
	return &SysBindTypeService{}
}

// 分页查询
func (*SysBindTypeService) Page(c context.Context, pageReq req_sys.SysBindTypePageReq) (*res.PageRes, error) {
	offset := (pageReq.Page - 1) * pageReq.PageSize
	q := repo_sys.SysBindType.WithContext(c)

	// 排序处理
	if pageReq.SortField != nil {
		sortField := utils.ConvertToSnakeCase(*pageReq.SortField)
		orderFieldExpr := field.NewUnsafeFieldRaw(sortField)
		if pageReq.SortOrder != nil {
			if *pageReq.SortOrder == "asc" {
				q = q.Order(orderFieldExpr.Asc())
			} else {
				q = q.Order(orderFieldExpr.Desc())
			}
		} else {
			q = q.Order(orderFieldExpr.Asc())
		}
	}

	// 执行分页查询
	list, count, err := q.FindByPage(offset, pageReq.PageSize)
	if err != nil {
		return nil, err
	}

	// 计算总页数
	page := res.PageRes{
		List:     list,
		Total:    count,
		Page:     pageReq.Page,
		PageSize: pageReq.PageSize,
		Pages:    int64(math.Ceil(float64(count) / float64(pageReq.PageSize))),
	}

	return &page, nil
}

// 添加 SysBindType 已开启事务
func (*SysBindTypeService) Add(c context.Context, addReq req_sys.SysBindTypeAddReq) (int64, error) {
	var SysBindType model_sys.SysBindType
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysBindType.WithContext(c)
		err := copier.Copy(&SysBindType, &addReq)
		if err != nil {
			return err
		}
		err = q.Create(&SysBindType)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return SysBindType.ID, nil
}

// 编辑 SysBindType 已开启事务
func (*SysBindTypeService) Edit(c context.Context, editReq req_sys.SysBindTypeEditReq) (int64, error) {
	var result gen.ResultInfo
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysBindType.WithContext(c).Where(repo_sys.SysBindType.ID.Eq(editReq.ID))
		SysBindType, err := q.First()
		if err != nil {
			return err
		}
		err = copier.Copy(&SysBindType, &editReq)
		if err != nil {
			return err
		}
		result, err = q.Updates(structs.Map(SysBindType))
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		if utils.IsOptimisticLockError(err) {
			return -1, nil // 乐观锁报错（版本不一致）
		}
		return 0, err
	}
	return result.RowsAffected, nil
}

// 删除 SysBindType 已开启事务
func (*SysBindTypeService) Delete(c context.Context, idsReq req.IdsReq) (int64, error) {
	var result gen.ResultInfo
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := repo_sys.SysBindType.WithContext(c)
		ids, err := idsReq.ToInt64Slice()
		if err != nil {
			return err
		}
		sysUserList, err := q.Where(repo_sys.SysUser.ID.In(ids...)).Find()
		if err != nil {
			return err
		}
		result, err = q.Delete(sysUserList...)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return result.RowsAffected, nil
}

// 查看 SysBindType 详情
func (*SysBindTypeService) Detail(c context.Context, userId int64) (*model_sys.SysBindType, error) {
	q := repo_sys.SysBindType.WithContext(c)
	SysBindType, err := q.Where(repo_sys.SysBindType.ID.Eq(userId)).First()
	if err != nil {
		return nil, err
	}
	return SysBindType, nil
}
